package custom.codegen

class CusSourceCodeGenerator(model: slick.model.Model)
  extends slick.codegen.SourceCodeGenerator(model) {
  override def code = {
    "import slick.model.ForeignKeyAction\n" +
      (if ( /*tables.exists(_.hlistEnabled)*/ true) {
        "import slick.collection.heterogeneous._\n" +
          "import slick.collection.heterogeneous.syntax._\n"
      } else "") +
      (if (tables.exists(_.PlainSqlMapper.enabled)) {
        "// NOTE: GetResult mappers for plain SQL are only generated for tables where Slick knows how to map the types of all columns.\n" +
          "import slick.jdbc.{GetResult => GR}\n"
      } else "") +
      (if (ddlEnabled) {
        "\n/** DDL for all tables. Call .create to execute. */" +
          (if (tables.length > 5)
            "\nlazy val schema: profile.SchemaDescription = Array(" + tables
            .map(_.TableValue.name + ".schema")
            .mkString(", ") + ").reduceLeft(_ ++ _)"
          else if (tables.nonEmpty)
            "\nlazy val schema: profile.SchemaDescription = " + tables
            .map(_.TableValue.name + ".schema")
            .mkString(" ++ ")
          else
            "\nlazy val schema: profile.SchemaDescription = profile.DDL(Nil, Nil)") +
          "\n@deprecated(\"Use .schema instead of .ddl\", \"3.0\")" +
          "\ndef ddl = schema" +
          "\n\n"
      } else "") +
      tables.map(_.code.mkString("\n")).mkString("\n\n")
  }

  override def Table = new Table(_) {
    override def PlainSqlMapper = new PlainSqlMapperDef {
      override def code: String = ""
    }
    override def compoundValue(values: Seq[String]): String = {
      values.mkString(" :: ") + " :: HNil"
    }
    override def TableClass = new TableClass {
      override def star = {
        val struct = compoundValue(columns.map(c =>
          if (c.asOption) s"Rep.Some(${c.name})" else s"${c.name}"))
        val rhs = s"($struct).mapTo[${TableClass.elementType}]"
        s"def * = $rhs"
      }
      override def option = ""

      override def code = {
        val prns = parents.map(" with " + _).mkString("")
        //这个不用，不加 schema name
        val args = model.name.schema.map(n => s"""Some("$n")""") ++ Seq(
          "\"" + model.name.table + "\"")
        val autalArgs = Seq("\"" + model.name.table + "\"")
        s"""
class $name(_tableTag: Tag) extends profile.api.Table[$elementType](_tableTag, ${
          autalArgs
            .mkString(", ")
        })$prns {
  ${indent(body.map(_.mkString("\n")).mkString("\n\n"))}
}
        """.trim()
      }
    }
    override def EntityType = new EntityTypeDef {
      override def classEnabled = true
    }
    override def Column = new Column(_) { column =>
      // customize db type -> scala type mapping, pls adjust it according to your environment
      override def rawType: String = model.tpe match {
        case "java.sql.Blob" => "Array[Byte]"
        case "java.sql.Clob" => "String"
        case _ => super.rawType
      }
    }
  }
}
